﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UniLua;

namespace TCG.FFI
{
    /// <summary>
    /// 向lua注册指定的导出库.
    /// </summary>
    public static class FFILibRegisterLib 
    {
        public const string LIB_NAME = "FFILibRegisterLib";

        public static int OpenLib (ILuaState luaState)
        {
            NameFuncPair[] exportFuncs = new NameFuncPair[] 
            {
				new NameFuncPair ("RegisterLib", RegisterLib)
            };
            luaState.L_NewLib (define:exportFuncs);
            return 1;
        }

        public static int RegisterLib (ILuaState luaState)
        {
            string libName = luaState.L_CheckString (1);

            System.Type libType = null;
            try
            {
                libType = System.Type.GetType ("TCG.FFI." + libName);
            }
            catch (System.TypeLoadException e)
            {
                Debug.LogError (e);
                return 0;
            }

			MethodInfo[] methods = libType.GetMethods (BindingFlags.Static | BindingFlags.Public);
			IList<NameFuncPair> memberFuncs = new List<NameFuncPair> ();
			IList<NameFuncPair> libFuncs = new List<NameFuncPair> ();

			for (int i = 0, len = methods.Length; i < len; ++ i)
			{
				MethodInfo mi = methods[i];
				if (mi.Name.StartsWith ("mf_"))
				{
					memberFuncs.Add (new NameFuncPair (mi.Name.Substring (3), Delegate.CreateDelegate (typeof (CSharpFunctionDelegate), mi) as CSharpFunctionDelegate));
				}
				else if (mi.Name.StartsWith ("lf_"))
				{
					libFuncs.Add (new NameFuncPair (mi.Name.Substring (3),Delegate.CreateDelegate (typeof (CSharpFunctionDelegate), mi) as CSharpFunctionDelegate));
				}
			}

			if (memberFuncs.Count == 0 && libFuncs.Count == 0) 
			{
				throw new Exception (string.Format ("尝试导出{0}时无法找到可用的函数", libName));
			}

			string parentLibName = string.Empty;
			FieldInfo fi = libType.GetField ("ParentLibName", BindingFlags.Static | BindingFlags.Public);
			if (fi != null)
			{
				parentLibName = (string)(fi.GetValue (null));
			}

			luaState.L_RequireF (libName, delegate(ILuaState state) {
				if (memberFuncs.Count > 0)
				{
					if (string.IsNullOrEmpty (parentLibName))
					{
						LuaTools.ExportLib (luaState, libName, libFuncs, memberFuncs);
					}
					else
					{
						LuaTools.ExportLibWithInheritance (luaState, libName, libFuncs, memberFuncs, parentLibName);
					}
				}
				else 
				{
					luaState.L_NewLib (libFuncs);
				}
				return 1;
			}, true);
            return 0;
        } 
    }
}
